
public class Cell {

	private static char MIN_RANK = '1';
	private static char MAX_RANK = '8';
	private static char MIN_FILE = 'a';
	private static char MAX_FILE = 'h';

	private static int FILE_INDEX = 0;
	private static int RANK_INDEX = 1;

	public int[] fileAndRank = new int[2];

	public Cell(int file, int rank) {
		String cellString = Character.toString((char) file) + Character.toString((char) rank);
		throwExceptionForInvalidCellString(cellString);
		fileAndRank[FILE_INDEX] = file;
		fileAndRank[RANK_INDEX] = rank;
	}

	public int rank() {
		return fileAndRank[RANK_INDEX];
	}

	public int file() {
		return fileAndRank[FILE_INDEX];
	}

	public int distanceBetweenRank(Cell other) {
		return fileAndRank[RANK_INDEX] - other.fileAndRank[RANK_INDEX];
	}

	public int distanceBetweenFile(Cell other) {
		return fileAndRank[FILE_INDEX] - other.fileAndRank[FILE_INDEX];
	}

	public boolean inSameRankAs(Cell other) {
		return distanceBetweenRank(other) == 0;
	}

	public boolean inSameFileAs(Cell other) {
		return distanceBetweenFile(other) == 0;
	}

	public boolean inDiagonalPathWith(Cell other) {
		return Math.abs(distanceBetweenFile(other)) == 
				Math.abs(distanceBetweenRank(other));
	}

	private void throwExceptionForInvalidCellString(String cellDescr) {
		if(cellDescr == null) throw new RuntimeException("Cell defined as null");
		if(cellDescr.length() != fileAndRank.length) throw new RuntimeException("Cell defined in non-existant position");
		if (cellDescr.charAt(FILE_INDEX) < MIN_FILE || 
				cellDescr.charAt(FILE_INDEX) > MAX_FILE) throw new RuntimeException("Invalid Cell File");
		if (cellDescr.charAt(RANK_INDEX) < MIN_RANK || 
				cellDescr.charAt(RANK_INDEX) > MAX_RANK) throw new RuntimeException("Invalid Cell Rank");
	}

	@Override
	public String toString() {
		return new String(fileAndRank);
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == null || !(obj instanceof Cell)) {
			return false;
		}

		Cell other = (Cell) obj;
		if (this.toString().equals(other.toString())) return true;
		else return false;
	}

	@Override
	public int hashCode() {
		return this.toString().hashCode();
	}
}
